/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.netease.financial.base.lockpattern;

import android.content.Context;
import android.util.Log;

import com.netease.financial.common.util.NfsLog;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Storage for the lock settings service.
 */
class LockSettingsStorage {

    private static final String TAG = "LockSettingsStorage";

    private static final String LOCK_PATTERN_FILE = "gatekeeper.pattern.key";

    private final Context mContext;
    private final Object mFileWriteLock = new Object();

    public LockSettingsStorage(Context context) {
        mContext = context;
    }

    public byte[] readPatternHash(String userId) {
        byte[] stored = readFile(getLockPatternFilename(userId));
        return stored;
    }

    public boolean hasPattern(String userId) {
        return hasFile(getLockPatternFilename(userId));
    }

    private boolean hasFile(String name) {
        byte[] contents = readFile(name);
        return contents != null && contents.length > 0;
    }

    private byte[] readFile(String name) {
        RandomAccessFile raf = null;
        byte[] stored = null;
        try {
            raf = new RandomAccessFile(name, "r");
            stored = new byte[(int) raf.length()];
            raf.readFully(stored, 0, stored.length);
            raf.close();
        } catch (IOException e) {
            Log.e(TAG, "Cannot read file " + e);
        } finally {
            if (raf != null) {
                try {
                    raf.close();
                } catch (IOException e) {
                    Log.e(TAG, "Error closing file " + e);
                }
            }
        }
        return stored;
    }

    private void writeFile(String name, byte[] hash) {
        synchronized (mFileWriteLock) {
            RandomAccessFile raf = null;
            try {
                // Write the hash to file
                raf = new RandomAccessFile(name, "rw");
                // Truncate the file if pattern is null, to clear the lock
                if (hash == null || hash.length == 0) {
                    raf.setLength(0);
                } else {
                    raf.write(hash, 0, hash.length);
                }
                raf.close();
            } catch (IOException e) {
                Log.e(TAG, "Error writing to file " + e);
            } finally {
                if (raf != null) {
                    try {
                        raf.close();
                    } catch (IOException e) {
                        Log.e(TAG, "Error closing file " + e);
                    }
                }
            }
        }
    }

    private void deleteFile(String name) {
        File f = new File(name);
        if (f != null) {
            f.delete();
        }
    }

    public void writePatternHash(byte[] hash, String userId) {
        writeFile(getLockPatternFilename(userId), hash);
    }

    public void clearPatternHash(String userId) {
        writeFile(getLockPatternFilename(userId), null);
    }

    String getLockPatternFilename(String userId) {
        return getLockCredentialFilePathForUser(userId, LOCK_PATTERN_FILE);
    }

    private String getLockCredentialFilePathForUser(String userId, String basename) {
        File file = new File(Environment.getUserSystemDirectory(mContext, userId), basename);

        String path = file.getAbsolutePath();
        NfsLog.d(TAG, "getLockCredentialFilePathForUser.path:" + path);
        return path;
    }

}
